home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include "global.h"
- #include "mbuf.h"
- #include "timer.h"
- #include "netuser.h"
- #include "socket.h"
- #include "cmdparse.h"
- #include "proc.h"
- #include "domain.h"
- #include "commands.h"
-
- static struct dserver *Dlist; /* List of potential servers */
- static struct dserver *Dserver; /* Current one being used */
- static char *Dsuffix; /* Default suffix for names without periods */
- static int Ddebug = 0;
- static char *Dtypes[] = {
- "",
- "A",
- "NS",
- "MD",
- "MF",
- "CNAME",
- "SOA",
- "MB",
- "MG",
- "MR",
- "NULL",
- "WKS",
- "PTR",
- "HINFO",
- "MINFO",
- "MX",
- "TXT"
- };
- static int Ndtypes = 17;
- static char delim[] = " \t\r\n";
- static struct {
- char *name;
- int32 address;
- } cache;
-
- static struct rr *dfind __ARGS((FILE *dbase,char *name,int type));
- static int doadds __ARGS((int argc,char *argv[],void *p));
- static int dodropds __ARGS((int argc,char *argv[],void *p));
- static int dolistds __ARGS((int argc,char *argv[],void *p));
- static int dosuffix __ARGS((int argc,char *argv[],void *p));
- static int dodtrace __ARGS((int argc,char *argv[],void *p));
- static void dumpdomain __ARGS((struct dhdr *dhdr,int32 rtt));
- static void free_dhdr __ARGS((struct dhdr *dp));
- static void free_qu __ARGS((struct quest *qp));
- static void free_rr __ARGS((struct rr *rrp));
- static struct rr *getrr __ARGS((FILE *fp));
- static int isaddr __ARGS((char *s));
- static void cache_response __ARGS((struct dhdr *dhdr));
- static void putrr __ARGS((FILE *fp,struct rr *rrp));
- static int res_mkquery __ARGS((int16 op,char *dname,int16 class,int16 type,
- char *data,int16 datalen,int16 newrr,char *buffer,int16 buflen));
- static int rrcmp __ARGS((struct rr *rr1,struct rr *rr2));
- static int sendquery __ARGS((int32 server,char *name,int type,int32 timeout,
- struct mbuf **bpp));
-
- static struct cmds Dcmds[] = {
- "addserver", doadds, 0, 2, NULLCHAR,
- "dropserver", dodropds, 0, 2, NULLCHAR,
- "listservers", dolistds, 0, 0, NULLCHAR,
- "suffix", dosuffix, 0, 0, NULLCHAR,
- "trace", dodtrace, 0, 0, NULLCHAR,
- NULLCHAR,
- };
-
- static int
- dodtrace(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Ddebug,"Domain trace",argc,argv);
- }
-
- int
- dodomain(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc == 1)
- return dolistds(argc,argv,p);
- return subcmd(Dcmds,argc,argv,p);
- }
-
- static int
- dosuffix(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2){
- if(Dsuffix != NULLCHAR)
- tprintf("%s\n",Dsuffix);
- return 0;
- }
- free(Dsuffix);
- Dsuffix = strdup(argv[1]);
- return 0;
- }
- static int
- doadds(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct dserver *dp;
- int32 address;
-
- if((address = resolve(argv[1])) == 0){
- tprintf("Resolver %s unknown\n",argv[1]);
- return 1;
- }
- dp = (struct dserver *)callocw(1,sizeof(struct dserver));
- dp->address = address;
- dp->srtt = (5L * 1000) / MSPTICK; /* About 5 sec */
- dp->mdev = 0;
- dp->timeout = 2 * dp->mdev + dp->srtt + 3;
- dp->next = Dlist;
- if(dp->next != NULLDOM)
- dp->next->prev = dp;
- Dlist = dp;
- Dserver = dp; /* Make this the first one we try next */
- return 0;
- }
- static int
- dodropds(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct dserver *dp;
- int32 addr;
-
- addr = resolve(argv[1]);
- for(dp = Dlist;dp != NULLDOM;dp = dp->next)
- if(addr == dp->address)
- break;
-
- if(dp == NULLDOM){
- tprintf("Not found\n");
- return 1;
- }
- if(dp->prev != NULLDOM)
- dp->prev->next = dp->next;
- else
- Dlist = dp->next;
- if(dp->next != NULLDOM)
- dp->next->prev = dp->prev;
-
- if(Dserver == dp)
- Dserver = Dlist;
- free((char *)dp);
- return 0;
- }
- static int
- dolistds(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct dserver *dp;
-
- tprintf("Server address srtt mdev timeout\
- queries responses\n");
- for(dp = Dlist;dp != NULLDOM;dp = dp->next){
- tprintf("%-20s%-8lu%-8lu%-8lu%-8lu%-8lu\n",
- inet_ntoa(dp->address),
- dp->srtt * MSPTICK,
- dp->mdev * MSPTICK,
- dp->timeout * MSPTICK,
- dp->queries,dp->responses);
- }
- return 0;
- }
-
- /* Search local domain file, starting at current position,
- * for resource record of specified type.
- * If a record is found, the domain file pointer is left just after it. If
- * not, it is left at end of file.
- */
- static struct rr *
- dfind(dbase,name,type)
- FILE *dbase;
- char *name;
- int type;
- {
- struct rr *rrp;
- int nlen;
-
- while((rrp = getrr(dbase)) != NULLRR){
- if( rrp->name
- && (nlen = strlen(name)) == strlen(rrp->name)
- && strnicmp(name,rrp->name,nlen) == 0
- && rrp->class == CLASS_IN
- && (type == TYPE_ANY || rrp->type == type))
- break;
- free_rr(rrp);
- pwait(NULL); /* Give up CPU for a while, this is slow */
- }
- return rrp;
- }
- static struct rr *
- getrr(fp)
- FILE *fp;
- {
- char *line,*strtok();
- struct rr *rrp;
- char *name,*ttl,*class,*type,*data;
- int i;
-
- line = mallocw(256);
- /* Search file */
- while(fgets(line,256,fp),!feof(fp)){
- if(line[0] != '#')
- break;
- }
- if(feof(fp)){
- free(line);
- return NULLRR;
- }
- rrp = (struct rr *)callocw(1,sizeof(struct rr));
- name = strtok(line,delim);
- ttl = strtok(NULLCHAR,delim);
- class = strtok(NULLCHAR,delim);
- type = strtok(NULLCHAR,delim);
- data = strtok(NULLCHAR,delim);
-
- if( ! type ) {
- free( line );
- return( rrp );
- }
-
- i = strlen(name);
- if(name[i-1] != '.'){
- /* Tack on a trailing period if it's not there */
- rrp->name = mallocw(i+2);
- strcpy(rrp->name,name);
- strcat(rrp->name,".");
- } else
- rrp->name = strdup(name);
-
- if(!isdigit(ttl[0])){
- /* Optional ttl field is missing; slide the other fields over */
- data = type;
- type = class;
- class = ttl;
- ttl = NULLCHAR;
- } else {
- rrp->ttl = atol(ttl);
- }
- for(i=0;i<NRLIST;i++){
- if(strcmp(type,Dtypes[i]) == 0){
- rrp->type = i;
- break;
- }
- }
- if(strcmp(class,"IN") == 0)
- rrp->class = CLASS_IN;
-
- if(data == NULLCHAR){
- /* Empty record, just return */
- free(line);
- return rrp;
- }
- switch(rrp->type){
- case TYPE_CNAME:
- case TYPE_MB:
- case TYPE_MG:
- case TYPE_MR:
- case TYPE_NS:
- case TYPE_PTR:
- case TYPE_TXT:
- rrp->rdlength = strlen(data);
- rrp->rdata.name = strdup(data);
- break;
- case TYPE_A:
- rrp->rdlength = 4;
- rrp->rdata.addr = aton(data);
- break;
- case TYPE_HINFO:
- rrp->rdlength = strlen(data);
- rrp->rdata.hinfo.cpu = strdup(data);
- if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
- rrp->rdlength += strlen(data);
- rrp->rdata.hinfo.os = strdup(data);
- }
- break;
- case TYPE_MX:
- rrp->rdata.mx.pref = atoi(data);
- rrp->rdlength = 2;
-
- /* Get domain name of exchanger */
- if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
- rrp->rdlength += strlen(data);
- rrp->rdata.mx.exch = strdup(data);
- }
- break;
- case TYPE_SOA:
- /* Get domain name of master name server */
- rrp->rdlength = strlen(data);
- rrp->rdata.soa.mname = strdup(data);
-
- /* Get domain name of irresponsible person */
- if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
- rrp->rdata.soa.rname = strdup(data);
- rrp->rdlength += strlen(data);
- }
- data = strtok(NULLCHAR,delim);
- rrp->rdata.soa.serial = atol(data);
- data = strtok(NULLCHAR,delim);
- rrp->rdata.soa.refresh = atol(data);
- data = strtok(NULLCHAR,delim);
- rrp->rdata.soa.retry = atol(data);
- data = strtok(NULLCHAR,delim);
- rrp->rdata.soa.expire = atol(data);
- data = strtok(NULLCHAR,delim);
- rrp->rdata.soa.minimum = atol(data);
- rrp->rdlength += 20;
- break;
- }
- free(line);
- return rrp;
- }
- /* Search for address record in local database, looking first for PTR
- * and CNAME records. Return values:
- * 0xffffffff Not found (domain name may exist, but we don't know yet)
- * 0 Domain name definitely doesn't exist (we have a null record)
- */
- int32
- dresolve(name)
- char *name;
- {
- register struct rr *rrp;
- char *sname,*tmp;
- int32 addr;
- FILE *dbase;
- int crecurse = 0;
- int found = 0;
-
- if(cache.name != NULLCHAR && strcmp(cache.name,name) == 0)
- return cache.address;
-
- if((dbase = fopen(Dfile,READ_TEXT)) == NULLFILE)
- return 0xffffffff;
-
- sname = strdup(name);
-
- while(!found && (rrp = dfind(dbase,sname,TYPE_ANY)) != NULLRR){
- switch(rrp->type){
- case TYPE_A:
- /* All set! */
- found++;
- if(rrp->rdlength == 0)
- addr = 0; /* Neg response */
- else
- addr = rrp->rdata.addr;
- break;
- case TYPE_CNAME:
- case TYPE_PTR:
- if(++crecurse == MAXCNAME){
- /* Too many CNAME recursions */
- found++;
- break;
- }
- /* Look for what it points to */
- tmp = strdup(rrp->rdata.name);
- free(sname);
- sname = tmp;
- rewind(dbase); /* Start again */
- break;
- }
- free_rr(rrp);
- }
- done: fclose(dbase);
- if(found){
- free(cache.name);
- cache.name = strdup(name);
- cache.address = addr;
- } else
- addr = 0xffffffff;
- free(sname);
- return addr;
- }
-
- /* Main entry point for domain name -> address resolution. Returns 0 if
- * name is definitely not valid.
- */
- int32
- resolve(name)
- char *name;
- {
- int32 addr;
- struct dhdr dhdr;
- struct dserver *dp = Dserver;
- char *sname,*tmp;
- int len,i;
- int32 rtt,abserr;
- struct mbuf *bp;
- struct rr *rrp;
- int crecurse = 0;
-
- if(name == NULLCHAR)
- return 0;
-
- if(*name == '[')
- return aton(name + 1);
-
- if(isaddr(name))
- return aton(name);
-
-
- sname = strdup(name);
- if(strchr(sname,'.') == NULLCHAR && Dsuffix != NULLCHAR){
- /* Append default suffix */
- tmp = mallocw(strlen(sname)+strlen(Dsuffix)+2);
- sprintf(tmp,"%s.%s",sname,Dsuffix);
- free(sname);
- sname = tmp;
- }
- if(sname[strlen(sname)-1] != '.'){
- /* Append trailing dot */
- tmp = mallocw(strlen(sname)+2);
- sprintf(tmp,"%s.",sname);
- free(sname);
- sname = tmp;
- }
- while((addr = dresolve(sname)) == 0xffffffff){
- /* Not found in local file. Query the domain servers. */
- if(dp == NULLDOM)
- break; /* no servers! */
- for(;;){
- dp->queries++;
- len = sendquery(dp->address,sname,TYPE_A,dp->timeout,&bp);
- if(len > 0)
- break; /* Got a response */
- if(errno == EABORT){
- addr = 0; /* Killed by "reset" command */
- break;
- }
- /* Timeout; back off this one and try another server */
- dp->timeout <<= 1;
- if((dp = dp->next) == NULLDOM)
- dp = Dlist;
- }
- if(len <= 0)
- break;
- dp->responses++;
- ntohdomain(&dhdr,&bp); /* Convert response to local format */
-
- /* Compute and update the round trip time */
- rtt = (int32) ((int16)Clock - dhdr.id);
- abserr = rtt > dp->srtt ? rtt - dp->srtt : dp->srtt - rtt;
- dp->srtt = ((AGAIN-1) * dp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
- dp->mdev = ((DGAIN-1) * dp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
- dp->timeout = 2 * dp->mdev + dp->srtt + 3;
-
- if(Ddebug)
- dumpdomain(&dhdr,rtt);
- cache_response(&dhdr); /* Add records to local disk file */
- /* Look for an answer in this response */
- for(i=0;i<dhdr.ancount;i++){
- rrp = dhdr.ans[i];
- if(strnicmp(rrp->name,sname,strlen(sname)) != 0)
- continue;
- /* Got one! */
- switch(rrp->type){
- case TYPE_CNAME:
- /* Change the query name to the cname
- * and go back again
- */
- if(++crecurse == MAXCNAME){
- /* Too many CNAME recursions */
- addr = 0;
- break;
- }
- free(sname);
- sname = strdup(rrp->rdata.name);
- /* Go back and rescan the response */
- i = -1;
- continue;
- case TYPE_A:
- if(rrp->rdlength == 0)
- addr = 0;
- else
- addr = rrp->rdata.addr;
- break;
- }
- break;
- }
- free_dhdr(&dhdr);
- if(addr != 0xffffffff)
- break;
- }
- free(sname);
- if(addr == 0xffffffff)
- addr = 0;
- return addr;
- }
- /* Send a query to a server */
- static int
- sendquery(server,name,type,timeout,bpp)
- int32 server; /* Server's IP address */
- char *name; /* Domain name being looked up */
- int type; /* Type of resource record sought */
- int32 timeout; /* Query timeout */
- struct mbuf **bpp; /* Place to stash reply */
- {
- char *buf;
- int len;
- struct sockaddr_in server_in;
- int s,rval;
-
- s = socket(AF_INET,SOCK_DGRAM,0);
- buf = mallocw(512);
- len = res_mkquery(0,name,CLASS_IN,TYPE_A,NULLCHAR,0,0,buf,512);
- server_in.sin_family = AF_INET;
- server_in.sin_port = IPPORT_DOMAIN;
- server_in.sin_addr.s_addr = server;
- if(Ddebug){
- printf("resolve: querying server %s for %s\n",
- inet_ntoa(server),name);
- }
- sendto(s,buf,len,0,(char *)&server_in,sizeof(server_in));
- free(buf);
- alarm(max(timeout,1));
- /* Wait for something to happen */
- rval = recv_mbuf(s,bpp,0,NULLCHAR,0);
- alarm(0L);
- close_s(s);
- return rval;
- }
-
- static int
- res_mkquery(op,dname,class,type,data,datalen,newrr,buffer,buflen)
- int16 op; /* operation */
- char *dname; /* Domain name */
- int16 class; /* Class of inquiry (IN, etc) */
- int16 type; /* Type of inquiry (A, MX, etc) */
- char *data;
- int16 datalen;
- int16 newrr;
- char *buffer; /* Area for query */
- int16 buflen; /* Length of same */
- {
- char *cp,*cp1;
- int16 parameter;
- int16 dlen,len;
-
- cp = buffer;
- cp = put16(cp,(int16)Clock); /* Use clock for timestamping */
- parameter = 0x100; /* Recursion desired */
- cp = put16(cp,parameter);
- cp = put16(cp,1);
- cp = put16(cp,0);
- cp = put16(cp,0);
- cp = put16(cp,0);
- dlen = strlen(dname);
- for(;;){
- /* Look for next dot */
- cp1 = strchr(dname,'.');
- if(cp1 != NULLCHAR)
- len = cp1-dname; /* More to come */
- else
- len = dlen; /* Last component */
- *cp++ = len; /* Write length of component */
- if(len == 0)
- break;
- /* Copy component up to (but not including) dot */
- strncpy(cp,dname,len);
- cp += len;
- if(cp1 == NULLCHAR){
- *cp++ = 0; /* Last one; write null and finish */
- break;
- }
- dname += len+1;
- dlen -= len+1;
- }
- cp = put16(cp,type);
- cp = put16(cp,class);
- return cp - buffer;
- }
- /* Append any non-duplicate resource records to the local file */
- static void
- cache_response(dhdr)
- struct dhdr *dhdr;
- {
- FILE *fp;
- int i;
- long ttl = 500; /* Default TTL for negative records without SOA */
- struct rr *rrp,*frrp;
- struct quest *qp;
-
- fp = fopen(Dfile,APPEND_TEXT);
- if(fp == NULLFILE){
- printf("Can't append to %s!!\n",Dfile);
- return;
- }
- /* Scan domain file looking for duplicates */
- while((frrp = getrr(fp)) != NULLRR){
- for(i=0;i< dhdr->ancount;i++){
- rrp = dhdr->ans[i];
- if(rrp->type == TYPE_SOA)
- ttl = rrp->ttl;
- if(rrcmp(rrp,frrp) == 0)
- rrp->dupe = 1;
- }
- for(i=0;i< dhdr->nscount;i++){
- rrp = dhdr->ns[i];
- if(rrp->type == TYPE_SOA)
- ttl = rrp->ttl;
- if(rrcmp(rrp,frrp) == 0)
- rrp->dupe = 1;
- }
- for(i=0;i< dhdr->arcount;i++){
- rrp = dhdr->add[i];
- if(rrp->type == TYPE_SOA)
- ttl = rrp->ttl;
- if(rrcmp(rrp,frrp) == 0)
- rrp->dupe = 1;
- }
- free_rr(frrp);
- }
- /* Now append any non-duplicate records */
- fseek(fp,0L,2);
- for(i=0;i< dhdr->ancount;i++){
- rrp = dhdr->ans[i];
- if(!rrp->dupe)
- putrr(fp,rrp);
- }
- for(i=0;i< dhdr->nscount;i++){
- rrp = dhdr->ns[i];
- if(!rrp->dupe)
- putrr(fp,rrp);
- }
- for(i=0;i< dhdr->arcount;i++){
- rrp = dhdr->add[i];
- if(!rrp->dupe)
- putrr(fp,rrp);
- }
- if(dhdr->aa && (dhdr->rcode == NAME_ERROR || dhdr->ancount == 0)){
- /* Add negative reply to file. This assumes that there was
- * only one question, which is true for all questions we send.
- */
- qp = dhdr->qlist[0];
- rrp = (struct rr *)callocw(1,sizeof(struct rr));
- rrp->name = strdup(qp->qname);
- rrp->type = qp->qtype;
- rrp->class = qp->qclass;
- rrp->ttl = ttl;
- rrp->rdlength = 0; /* no data */
- putrr(fp,rrp);
- free_rr(rrp);
- }
- fclose(fp);
- }
- /* Print a resource record */
- static void
- putrr(fp,rrp)
- FILE *fp;
- struct rr *rrp;
- {
- if(fp == NULLFILE || rrp == NULLRR)
- return;
-
- fprintf(fp,"%s\t%lu",rrp->name,rrp->ttl);
- if(rrp->class == CLASS_IN)
- fprintf(fp,"\tIN");
- else
- fprintf(fp,"\t%u",rrp->class);
- if(rrp->type < Ndtypes)
- fprintf(fp,"\t%s",Dtypes[rrp->type]);
- else
- fprintf(fp,"\t%u",rrp->type);
- if(rrp->rdlength == 0){
- /* Null data portion, indicates nonexistent record */
- fprintf(fp,"\n");
- return;
- }
- switch(rrp->type){
- case TYPE_CNAME:
- case TYPE_MB:
- case TYPE_MG:
- case TYPE_MR:
- case TYPE_NS:
- case TYPE_PTR:
- case TYPE_TXT:
- /* These are all printable text strings */
- fprintf(fp,"\t%s\n",rrp->rdata.data);
- break;
- case TYPE_A:
- fprintf(fp,"\t%s\n",inet_ntoa(rrp->rdata.addr));
- break;
- case TYPE_MX:
- fprintf(fp,"\t%u\t%s\n",rrp->rdata.mx.pref,
- rrp->rdata.mx.exch);
- break;
- case TYPE_SOA:
- fprintf(fp,"\t%s\t%s\t%lu\t%lu\t%lu\t%lu\t%lu\n",
- rrp->rdata.soa.mname,rrp->rdata.soa.rname,
- rrp->rdata.soa.serial,rrp->rdata.soa.refresh,
- rrp->rdata.soa.retry,rrp->rdata.soa.expire,
- rrp->rdata.soa.minimum);
- break;
- default:
- fprintf(fp,"\n");
- break;
- }
- }
- /* Free a domain message */
- static void
- free_dhdr(dp)
- struct dhdr *dp;
- {
- int i;
-
- if(dp->qdcount != 0){
- for(i=0;i<dp->qdcount;i++)
- free_qu(dp->qlist[i]);
- free((char *)dp->qlist);
- }
- if(dp->ancount != 0){
- for(i=0;i<dp->ancount;i++)
- free_rr(dp->ans[i]);
- free((char *)dp->ans);
- }
- if(dp->nscount != 0){
- for(i=0;i<dp->nscount;i++)
- free_rr(dp->ns[i]);
- free((char *)dp->ns);
- }
- if(dp->arcount != 0){
- for(i=0;i<dp->arcount;i++)
- free_rr(dp->add[i]);
- free((char *)dp->add);
- }
- }
-
- /* Free a question record */
- static void
- free_qu(qp)
- struct quest *qp;
- {
- free(qp->qname);
- free((char *)qp);
- }
-
- /* Free a resource record */
- static void
- free_rr(rrp)
- struct rr *rrp;
- {
- if(rrp == NULLRR)
- return;
- free(rrp->name);
- if(rrp->rdlength != 0){
- switch(rrp->type){
- case TYPE_CNAME:
- case TYPE_MB:
- case TYPE_MG:
- case TYPE_MR:
- case TYPE_NS:
- case TYPE_PTR:
- free(rrp->rdata.name);
- break;
- case TYPE_A:
- break; /* Nothing allocated in rdata section */
- case TYPE_HINFO:
- free(rrp->rdata.hinfo.cpu);
- free(rrp->rdata.hinfo.os);
- break;
- case TYPE_MX:
- free(rrp->rdata.mx.exch);
- break;
- case TYPE_SOA:
- free(rrp->rdata.soa.mname);
- free(rrp->rdata.soa.rname);
- break;
- case TYPE_TXT:
- free(rrp->rdata.data);
- break;
- }
- }
- free((char *)rrp);
- }
- /* Compare two resource records, returning 0 if equal, nonzero otherwise */
- static int
- rrcmp(rr1,rr2)
- register struct rr *rr1,*rr2;
- {
- int i;
-
- if(rr1 == NULLRR || rr2 == NULLRR)
- return -1;
- if((i = strlen(rr1->name)) != strlen(rr2->name))
- return 1;
- if((i = strnicmp(rr1->name,rr2->name,i)) != 0)
- return i;
- if(rr1->type != rr2->type)
- return 2;
- if(rr1->class != rr2->class)
- return 3;
- /* Note: rdlengths are not compared because they vary depending
- * on the representation (ASCII or encoded) this record was
- * generated from.
- */
- switch(rr1->type){
- case TYPE_A:
- i = rr1->rdata.addr != rr2->rdata.addr;
- break;
- case TYPE_SOA:
- i = rr1->rdata.soa.serial != rr2->rdata.soa.serial;
- break;
- case TYPE_HINFO:
- i = strcmp(rr1->rdata.hinfo.cpu,rr2->rdata.hinfo.cpu) ||
- strcmp(rr1->rdata.hinfo.os,rr2->rdata.hinfo.os);
- break;
- case TYPE_MX:
- i = strcmp(rr1->rdata.mx.exch,rr2->rdata.mx.exch);
- break;
- case TYPE_MB:
- case TYPE_MG:
- case TYPE_MR:
- case TYPE_NULL:
- case TYPE_WKS:
- case TYPE_PTR:
- case TYPE_MINFO:
- case TYPE_TXT:
- case TYPE_NS:
- i = strcmp(rr1->rdata.data,rr2->rdata.data);
- break;
- case TYPE_MD:
- case TYPE_MF:
- case TYPE_CNAME:
- i = strcmp(rr1->rdata.data,rr2->rdata.data);
- break;
- }
- return i;
- }
- /* Return 1 if string appears to be an IP address in dotted decimal;
- * return 0 otherwise (i.e., if string is a domain name)
- */
- static int
- isaddr(s)
- register char *s;
- {
- char c;
-
- if(s == NULLCHAR)
- return 1; /* Can't happen */
-
- while((c = *s++) != '\0'){
- if(!isdigit(c) && c != '.')
- return 0;
- }
- return 1;
- }
- static void
- dumpdomain(dhdr,rtt)
- struct dhdr *dhdr;
- int32 rtt;
- {
- int i;
- struct rr *rrp;
- struct quest *qp;
-
- printf("response id %u (rtt %lu sec) qr %u opcode %u aa %u tc %u rd %u ra %u rcode %u\n",
- dhdr->id,((long)rtt * MSPTICK)/1000,
- dhdr->qr,dhdr->opcode,dhdr->aa,dhdr->tc,dhdr->rd,
- dhdr->ra,dhdr->rcode);
- printf("%u questions:\n",dhdr->qdcount);
- for(i=0;i< dhdr->qdcount;i++){
- qp = dhdr->qlist[i];
- printf("%s type %u class %u\n",qp->qname,
- qp->qtype,qp->qclass);
- }
- printf("%u answers:\n",dhdr->ancount);
- for(i=0;i< dhdr->ancount;i++){
- rrp = dhdr->ans[i];
- putrr(stdout,rrp);
- }
- printf("%u authority:\n",dhdr->nscount);
- for(i=0;i< dhdr->nscount;i++){
- rrp = dhdr->ns[i];
- putrr(stdout,rrp);
- }
- printf("%u additional:\n",dhdr->arcount);
- for(i=0;i< dhdr->arcount;i++){
- rrp = dhdr->add[i];
- putrr(stdout,rrp);
- }
- fflush(stdout);
- }
-
-